package com.logansoft.zhxypkoa.filter;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.web.filter.OncePerRequestFilter;

import com.logansoft.zhxypkoa.components.JwtTool;
import com.logansoft.zhxypkoa.components.JwtUser;
import com.logansoft.zhxypkoa.components.UrlTool;
import com.logansoft.zhxypkoa.domain.Actions;
import com.logansoft.zhxypkoa.domain.sys.Premission;
import com.logansoft.zhxypkoa.domain.sys.User;
import com.logansoft.zhxypkoa.repository.sys.PremissionRepository;
import com.logansoft.zhxypkoa.repository.sys.UserRepository;

/**
 * 拦截请求, 检验 http header 中的 JWT 信息
 * 
 * @author zhuyj
 *
 */
//@WebFilter(filterName = "JwtAuthenticationTokenFilter", urlPatterns = "/api/*")
//@Order(value = 1)
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

	@Autowired
	private JwtTool jwtTool;
	@Autowired
	private UrlTool urlTool;
	@Autowired
	private PremissionRepository premissionRepository;
	@Autowired
	private UserRepository userRepository;
	
	/*public JwtAuthenticationTokenFilter() {
		// TODO Auto-generated constructor stub
		super();
	}*/

	private String tokenHeader = "Authorization";

	private String tokenHead = "Bearer ";

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
			throws ServletException, IOException {
		/*if (request.getMethod().toLowerCase().equals("options")) {
			// allows
			logger.info("跳过 option 请求");
			chain.doFilter(request, response);
			return;
		}*/
		
		String authHeader = request.getHeader(this.tokenHeader);
		logger.info("this.tokenHeader: " + this.tokenHeader);
		logger.info("request.getHeader(this.tokenHeader): " + authHeader);

		String path = request.getRequestURI().substring(request.getContextPath().length()).replaceAll("[/]+$", "");
		logger.info("this path: " + path);
		
		String resource = urlTool.findResource(path);
		logger.info("访问的资源为: " + resource);
		if (null == resource) {
			response.sendError(HttpServletResponse.SC_NOT_FOUND, "can not find resource.");
			return;
		}
		
		String userId = null;
		boolean hasAuth = false;
		
		// HttpSession session = request.getSession();
		if (authHeader != null && authHeader.startsWith(this.tokenHead) && authHeader.length() > 20) {
			hasAuth = true;
			String authToken = authHeader.substring(this.tokenHead.length());
			/*if (authHeader != null && authHeader.startsWith(this.tokenHead)) {
				authToken = authHeader.substring(this.tokenHead.length());
			}*/

			userId = jwtTool.getUsernameFromToken(authToken);

			HttpSession httpSession = request.getSession();
			httpSession.setAttribute("userId", userId);

			logger.info("checking authentication " + userId);

		}
		
		boolean allowedPath = urlTool.match(path);

		if (allowedPath) {
			logger.info("这里是不需要处理的url进入的方法");
			chain.doFilter(request, response);
			return;
		} else if (!allowedPath && !hasAuth) {
			logger.info("没有携带认证");
			response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "REST Api need authorization.");
			return;
		}
		
		if (userId != null && !userId.equals("")) {
			try {
				Optional<User> user = userRepository.findById(userId);
				if (user != null && user.get().getUsername().equals("admin")) {
					logger.info("跳过管理员的权限验证");
					chain.doFilter(request, response);
					return;
				}
				/*JwtUser jwtUser = null;

				if (!jwtTool.validateToken(authToken, jwtUser)) {
					// 验证不通过
					response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "REST signature failed validation.");
					return;
				}*/
				// 请求方法, 跟 Action 做对比
				String method = request.getMethod().toLowerCase();
				logger.info("请求方法: " + method);
				// 每次请求执行的搜索效率很低
				List<Premission> premissionList = premissionRepository.findListByUserId(userId);
				for (int i = 0; i < premissionList.size(); i ++) {
					Premission item = premissionList.get(i);
					logger.info("用户: " + userId + " 拥有对资源: " + item.getResource().getDescription() + " 访问权限: " + item.getAction());
					// 只简单判断, 还有各种自定义的 url 没有拦截, 例如采用 post 请求的批量删除方法
					if (resource.equals(item.getResource().getDescription())
							&& (("get".equals(method) && item.getAction().equals(Actions.SEARCH))
									|| ("post".equals(method) && item.getAction().equals(Actions.CREATE))
									|| (("put".equals(method) || "patch".equals(method))
											&& item.getAction().equals(Actions.UPDATE))
									|| ("delete".equals(method) && item.getAction().equals(Actions.DELETE)))) {
						logger.info("符合权限: " + item.getAction() + " 资源: " + resource);
						chain.doFilter(request, response);
						return;
					}
				}
				response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "the method or resource not allowed for you.");
				return;
			} catch (Exception e) {
				e.printStackTrace();
				response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
						"The REST Security Server experienced an internal error.");
				return;
			}
		} else {
			logger.info("认证解析无效");
			response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "unknow authorization headers.");
			return;
		}
	}
}
